﻿/************************************************************************

 This file is part of EscapeFromPrisonPlanet.

 EscapeFromPrisonPlanet is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 EscapeFromPrisonPlanet is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with Foobar.  If not, see <http://www.gnu.org/licenses/>.

************************************************************************/

// All code (c)2012 Scott Bevin. all rights reserved

using System.Collections.Generic;
using Microsoft.Xna.Framework.Graphics;

namespace LudumDare25Project
{
    internal class GameScreenManager
    {
        private InputManager ActualInputManager = new InputManager();
        private InputManager DummyInputManager = new InputManager();

        private GameMain Game = null;
        private SpriteBatch SpriteBatch = null;

        public List<GameScreen> GameScreens = new List<GameScreen>();

        public struct AddGameScreenData
        {
            public GameScreen GameScreen;
            public GameScreen Ref;

            public enum PositioningOptions
            {
                OnTop,
                OnBottom,
                AboveRef,
                BelowRef,
            }

            public PositioningOptions Positioning;
        }

        private List<AddGameScreenData> GameScreensToAdd = new List<AddGameScreenData>();

        public GameScreenManager(GameMain game)
        {
            Game = game;
            SpriteBatch = new SpriteBatch(game.GraphicsDevice);
        }

        public void AddGameScreen(GameScreen screen, GameScreen Ref, AddGameScreenData.PositioningOptions positioning)
        {
            screen.Setup(this, Game);

            AddGameScreenData agds = new AddGameScreenData();
            agds.GameScreen = screen;
            agds.Ref = Ref;
            agds.Positioning = positioning;

            GameScreensToAdd.Add(agds);
        }

        public void Update(float dt)
        {
            ActualInputManager.Update();

            while (GameScreensToAdd.Count > 0)
            {
                List<AddGameScreenData> addScreens = new List<AddGameScreenData>(GameScreensToAdd);
                GameScreensToAdd.Clear();

                foreach (AddGameScreenData gs in addScreens)
                {
                    gs.GameScreen.OnAdded();

                    if (gs.Positioning == AddGameScreenData.PositioningOptions.OnBottom)
                    {
                        GameScreens.Insert(0, gs.GameScreen);
                    }
                    else if (gs.Positioning == AddGameScreenData.PositioningOptions.OnTop || gs.Ref == null)
                    {
                        GameScreens.Add(gs.GameScreen);
                    }
                    else if (gs.Positioning == AddGameScreenData.PositioningOptions.AboveRef)
                    {
                        bool found = false;

                        for (int i = 0; i < GameScreens.Count; ++i)
                        {
                            if (GameScreens[i] == gs.Ref)
                            {
                                found = true;
                                GameScreens.Insert(i + 1, gs.GameScreen);

                                break;
                            }
                        }

                        if (!found)
                            GameScreens.Add(gs.GameScreen);
                    }
                    else if (gs.Positioning == AddGameScreenData.PositioningOptions.BelowRef)
                    {
                        bool found = false;

                        for (int i = 0; i < GameScreens.Count; ++i)
                        {
                            if (GameScreens[i] == gs.Ref)
                            {
                                found = true;
                                GameScreens.Insert(i, gs.GameScreen);

                                break;
                            }
                        }

                        if (!found)
                            GameScreens.Add(gs.GameScreen);
                    }
                }
            }

            List<GameScreen> GameScreensToRemove = new List<GameScreen>();

            for (int i = 0; i < GameScreens.Count; ++i)
            {
                GameScreens[i].Update(dt, (i == GameScreens.Count - 1) ? ActualInputManager : DummyInputManager);

                if (GameScreens[i].KillScreen)
                    GameScreensToRemove.Add(GameScreens[i]);
            }

            foreach (GameScreen gs in GameScreensToRemove)
            {
                gs.OnRemoved();
                GameScreens.Remove(gs);
            }

#if DEBUG
            DebugDraw.Get.AddText("GameScreens:");
            foreach (GameScreen gs in GameScreens)
                DebugDraw.Get.AddText(" - " + gs.ToString());
#endif
        }

        public void Render(float dt, GraphicsDevice gd)
        {
            for (int i = GameScreens.Count - 1; i >= 0; --i)
            {
                if (GameScreens[i].Fullscreen)
                {
                    for (int j = 0; j < GameScreens.Count; ++j)
                    {
                        GameScreens[j].Render(dt, gd, SpriteBatch);
                    }
                }
            }
        }
    }
}